home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / pine / osdep / dosextra < prev    next >
Text File  |  1996-06-06  |  13KB  |  556 lines

  1. #line 2 "osdep/dosextra"
  2.  
  3. /*
  4.  * map the ftruncate call into DOS' chsize
  5.  */
  6. int
  7. ftruncate(fd, size)
  8.     int     fd;
  9.     long size;
  10. {
  11.     return(chsize(fd, size));
  12. }
  13.  
  14.  
  15. #ifndef OS2
  16. /*
  17.  * have_ printer - use BIOS int 0x17 to get a system equipment list
  18.  *           returning whether or not there's a printer
  19.  */
  20. have_printer()
  21. {
  22.     union REGS rg;
  23.  
  24.     int86(0x11, &rg, &rg);        /* what's there ? */
  25.     return(rg.x.ax & 0xc000);        /* any printers ? */
  26. }
  27.  
  28.  
  29. /*
  30.  * printer_status - get printer status using BIOS printer services (int 17h)
  31.  *             return 0 if printer responds bad status otherwise.
  32.  */
  33. unsigned short printer_ready()
  34. {
  35.     union REGS rg;
  36.  
  37.     if(!have_printer())            /* bother to get stat ? */
  38.       return(0xffff);
  39.  
  40.     rg.h.ah = 0x02;            /* get printer status */
  41.     rg.x.dx = 0;            /* which printer */
  42.     int86(0x17, &rg, &rg);        /* do it */
  43.  
  44.     return(rg.h.ah & ~(0xd6));        /* 0x10, 0x40 & 0x80 are OK */
  45.                     /* 0x02 and 0x04 are ignored */
  46. }
  47.  
  48.  
  49. /*
  50.  * p_printer_error - given a a byte of error code, return the string
  51.  *                   corresponding to it.
  52.  */
  53. char *p_printer_error(err)
  54. unsigned short err;
  55. {
  56.     if(err == 0xffff)
  57.     return("No printer found");
  58.     else if(err & 0x01)
  59.     return("Status 1: Time out (on line?)");
  60.     else if(err & 0x08)
  61.     return("Status 8: I/O error");
  62.     else if(err & 0x20)
  63.     return("Status 32: Out of paper ");
  64.     else if(err & 0x40 || err & 0x80 || err & 0x10)
  65.     /* ACK from printer or printer NOT busy or printer selected */
  66.     return("");
  67.     else
  68.         return("Weird printer status");
  69. }
  70.  
  71.  
  72. /*
  73.  * send_printer - write a byte to the printer returning status 
  74.  */
  75. int send_printer(c)
  76. char c;
  77. {
  78.     union REGS rg;
  79.  
  80.     rg.h.ah = 0;            /* service 0: send a byte */
  81.     rg.h.al = c;            /* which byte */
  82.     rg.x.dx = 0;            /* which printer */
  83.     int86(0x17, &rg, &rg);        /* do it */
  84.     return(rg.h.ah & ~(0xd6));        /* 0x10, 0x40 & 0x80 are OK */
  85.                     /* 0x02 and 0x04 are ignored */
  86. }
  87.  
  88.  
  89. /*
  90.  * coreleft - returns the amount of core memory currently available
  91.  */
  92. long
  93. coreleft()
  94. {
  95. #ifdef _WINDOWS
  96.     return (GetFreeSpace (0));
  97. #else
  98.     long ramfree = 0L;
  99.     register int i = 0, j;
  100.     static unsigned segs[10];
  101.     union  REGS r;
  102.     struct SREGS s;
  103.  
  104.     while(1){
  105.         r.h.ah = 0x48;            /* DOS alloc a paragraph */
  106.         r.x.bx = 0x0001;        /* grab 1 paragraph (16 bytes) */
  107.         intdos(&r, &r);
  108.         if(r.x.cflag){            /* carry flag set, no more core */
  109.         for(j=0;j<i;j++){
  110.                 r.h.ah = 0x49;        /* DOS free alloc'd core */
  111.                 s.es = segs[j];        /* segment to free */
  112.                 intdosx(&r, &r, &s);
  113.         }
  114.         return(ramfree*16L);
  115.         }
  116.     else
  117.             segs[i] = r.x.ax;        /* remember the sigment */
  118.  
  119.         r.h.ah = 0x4a;            /* DOS resize alloc'd core */
  120.         r.x.bx = 0xffff;        /* grab the biggest we can */
  121.         s.es = segs[i];            /* segment to resize */
  122.         intdosx(&r, &r, &s);
  123.  
  124.     if(r.x.cflag){
  125.             r.h.ah = 0x4a;            /* DOS resize alloc'd core */
  126.             s.es = segs[i];            /* segment to resize */
  127.             intdosx(&r, &r, &s);
  128.         ramfree += r.x.bx;
  129.     }
  130.         else
  131.         ramfree += 0xffff;
  132.  
  133.         i++;
  134.     }
  135. #endif
  136. }
  137. #endif
  138.  
  139. /*
  140.  * OS unique c-client calls and such.
  141.  */
  142.  
  143.  
  144. /*
  145.  * zone_offset - print the time zone offset in local differential
  146.  *               form : hours+minutes (HHMM)
  147.  */
  148. void
  149. zone_offset(buf)
  150. char *buf;
  151. {
  152.     struct timeb tb;
  153.  
  154.     ftime(&tb);
  155.     sprintf(buf, "%02.2u%02.2u", tb.timezone/60, tb.timezone%60);
  156. }
  157.  
  158.  
  159. #ifndef OS2
  160. /*
  161.  * Special hook so externally we can avoid copying from one file to
  162.  * another.  It's quite a hack, and not exactly clear, but does help
  163.  * performance-wise.
  164.  */
  165. FILE *append_file = NULL;
  166.  
  167. /*
  168.  * dos_gets - c-client callback for mail_fetchbody to use when receiving 
  169.  *            a message text too large for free mem (see mailview.c).
  170.  */
  171. char *dos_gets (f, stream, size)
  172. readfn_t  f;
  173. void     *stream;
  174. unsigned long      size;
  175. {
  176.     char tmp[MAILTMPLEN+1];
  177.     unsigned long j = 0L;
  178.     extern unsigned long gets_bytes;
  179.  
  180.     if(!append_file){
  181.     char es[128];
  182.     /* post error message, dump the text in the bit bucket */
  183.     mm_log("dos_gets: NO FILE HANDLE TO APPEND",ERROR);
  184.     return(NULL);
  185.     }
  186.  
  187.     while(size -= j){
  188.     (*f) (stream, j = min ((long) MAILTMPLEN, size), tmp);
  189.     gets_bytes += j;
  190. #ifndef    _WINDOWS
  191.     win_multiplex();
  192. #endif
  193.     if(fwrite(tmp, sizeof(char), (size_t)j, append_file) != j){
  194.         /* problem writing temp file! bail gracefully */
  195.         sprintf(tmp,"Error getting message: %s", error_description(errno));
  196.         mm_log(tmp, ERROR);
  197.         return(NULL);
  198.         }
  199.     }
  200.  
  201.     return(cpystr("programmer botch: data on disk"));
  202. }
  203.  
  204.  
  205. /*
  206.  *                   ******* DOS Cache Manager *******
  207.  *
  208.  * Each mail stream has associated with it a cache of mail elements 
  209.  * ("elt" in c-client parlance).  This can get too ponderous slog around
  210.  * in the 640K *MAX* that DOS allows, so the idea is to manager some number
  211.  * of them in core and page the rest out to disk.  ALL CACHE ACCESS IN
  212.  * C-CLIENT MUST TO GO THRU THE mailcache() FUNCTION!!
  213.  *
  214.  */
  215.  
  216.  
  217. /*
  218.  * CacheBlock_SIZE: number of elt's cached in core at any one time
  219.  */
  220. #define    CB_SIZE    (20L)
  221.  
  222.  
  223. /*
  224.  * Meta cache structure.  Used by dos_cache to hold either short or long
  225.  * elt's and a flag reporting if the entry's been accessed/used or not.
  226.  */
  227. typedef struct metacache {
  228.     short        use;        /* cache slot in use flag */
  229.     union {
  230.     MESSAGECACHE    mc;
  231.     LONGCACHE    lc;
  232.     } cachel;                /* access to cache elements */
  233. } METACACHE;
  234.  
  235.  
  236. /*
  237.  * Master DOS cache structure.  Every mail stream gets one, and has it
  238.  * until it dies.  c-client worries about freeing this with a CH_INIT.
  239.  */
  240. typedef struct doscache {
  241.     FILE        *dcf;        /* DOS cache file pointer */
  242.     char        *name;        /* DOS cache file's name  */
  243.         long        cbase;        /* index of array in slot 1 of block */
  244.     METACACHE    mcb[CB_SIZE];    /* meta cache block */
  245. } DOSCACHE;
  246.  
  247.  
  248. /*
  249.  * dcreadb - dos cache read block; given a stream, read a new block
  250.  *         of cache entries into core.  Doscache's cbase field
  251.  *           describes where to start loading.
  252.  */
  253. void dcreadb(cache)
  254. DOSCACHE *cache;
  255. {
  256.     size_t n;
  257.     
  258.     if(fseek(cache->dcf, cache->cbase * sizeof(METACACHE), SEEK_SET))
  259.       fatal("ran off end of dos cache file in dcreadb");
  260.  
  261.     n = fread((void *)&cache->mcb[0],sizeof(METACACHE),
  262.         (size_t)CB_SIZE,cache->dcf);
  263.  
  264.     if(n != CB_SIZE)
  265.       fatal("Can't read cache block in from disk");
  266. }
  267.  
  268.  
  269. /*
  270.  * dcwriteb - dos cache write block; given a stream, write the current 
  271.  *            block of cache entries to disk.  Guaranteed write, or fatal.
  272.  */
  273. void dcwriteb(cache)
  274. DOSCACHE *cache;
  275. {
  276.     size_t n;
  277.  
  278.     if(fseek(cache->dcf, cache->cbase * sizeof(METACACHE), SEEK_SET))
  279.       fatal("ran off end of dos cache file in dcwriteb");
  280.  
  281.     n = fwrite(&cache->mcb[0], sizeof(METACACHE), (size_t)CB_SIZE, cache->dcf);
  282.  
  283.     if(n != CB_SIZE)
  284.       fatal("Can't write cache block to from disk");
  285. }
  286.  
  287.  
  288.  
  289. /*
  290.  * dchit - make sure metacache entry for msgno is in core, if not, 
  291.  *         write current block and read in new one that contains it.
  292.  */
  293. void dchit(cache, msgno)
  294. DOSCACHE *cache;
  295. long      msgno;
  296. {
  297.     long i = msgno - 1;            /* index of msgno's elt */
  298.     size_t n;
  299.  
  300.     if(msgno <= 0)
  301.       fatal("bogus msgno passed to dchit");
  302.  
  303.     if(i >= cache->cbase && i < cache->cbase + CB_SIZE)
  304.       return;                /* everything's okey dokey */
  305.  
  306.     dcwriteb(cache);            /* roll out the current block */
  307.  
  308.     cache->cbase = (i/CB_SIZE) * CB_SIZE;
  309.     dcreadb(cache);            /* roll in the new block */
  310. }
  311.  
  312.  
  313.  
  314. /*
  315.  * dcget - dos cache get; given a stream and a message number in it, 
  316.  *         return a pointer to the cache entry associated with it.
  317.  */
  318. METACACHE *dcget(stream, msgno)
  319. MAILSTREAM *stream;
  320. long        msgno;
  321. {
  322.     int i;
  323.     DOSCACHE *dc = (DOSCACHE *)stream->cache.c;
  324.  
  325.     dchit(dc, msgno);            /* correct block in core? */
  326.  
  327.     i = (int)((msgno-1)%CB_SIZE);    /* offset of entry in block */
  328.     if(!dc->mcb[i].use){        /* new cache entry! */
  329.     memset((void *)&dc->mcb[i], 0, sizeof(METACACHE));
  330.     dc->mcb[i].use = 1;        /* mark entry as accessed */
  331.     if(stream->scache){
  332.         dc->mcb[i].cachel.mc.lockcount = 1;
  333.         dc->mcb[i].cachel.mc.msgno = msgno;
  334.     }
  335.     else{
  336.         dc->mcb[i].cachel.lc.elt.lockcount = 1;
  337.         dc->mcb[i].cachel.lc.elt.msgno = msgno;
  338.         dc->mcb[i].cachel.lc.env = NULL;
  339.         dc->mcb[i].cachel.lc.body = NULL;
  340.     }
  341.     }
  342.  
  343.     return(&dc->mcb[i]);
  344. }
  345.  
  346.  
  347.  
  348. /*
  349.  * dos_cache - c-client callback used to manage cached elt's and 
  350.  *             envelopes. (see ../c-client/mail.c)
  351.  */
  352. void *dos_cache(stream, msgno, op)
  353. MAILSTREAM *stream;
  354. long        msgno;
  355. long        op;
  356. {
  357.     size_t n;
  358.     void *ret = NULL;
  359.     long i = msgno - 1;
  360.     unsigned long j = stream->cachesize;
  361.     METACACHE ctmp;
  362.     DOSCACHE  *dtmp = (DOSCACHE *)stream->cache.c;
  363.  
  364.     switch ((int) op) {            /* what function? */
  365.       case CH_INIT:            /* initialize cache */
  366.         if (stream->cachesize) {    /* flush old cache contents */
  367.         
  368.         /*
  369.          * WARNING: if lock counts are ever important, this will 
  370.          *          have to become a loop counting down the 
  371.          *          cachesize and calling something like 
  372.          *          mail_free_elt() for each one!
  373.          */
  374.         fclose(dtmp->dcf); /* should auto blast tmpfile */
  375.         if(dtmp->name){
  376.         unlink(dtmp->name);
  377.         free(dtmp->name);
  378.         dtmp->name = NULL;
  379.         }
  380.  
  381.         fs_give((void **)&stream->cache.c);
  382.         stream->cachesize = 0;
  383.         }
  384.         break;
  385.  
  386.       case CH_SIZE:            /* (re-)size the cache */
  387.         if (msgno > j) {        /* do nothing if size adequate */
  388.         /*
  389.          * TUNING POTENTIAL: the const 4 below could be tweeked
  390.          */
  391.         while(msgno > stream->cachesize)
  392.           stream->cachesize += (CB_SIZE * 4);
  393.  
  394.             if (stream->cache.c == NULL){
  395.         stream->cache.c = (void *)fs_get(sizeof(DOSCACHE));
  396.         memset(stream->cache.c, 0, sizeof(DOSCACHE));
  397.         dtmp = (DOSCACHE *)stream->cache.c;
  398.         if(!dtmp->name)
  399.           dtmp->name = temp_nam(NULL, "pi");
  400.  
  401.         /*
  402.          * Can't use tmpfile() as MSC's library call won't 
  403.          * observe TMP or TEMP env vars.  Wonders never cease.
  404.          */
  405.         if((dtmp->dcf = (void *)fopen(dtmp->name, "w+b")) == NULL){
  406.             sprintf(tmp_20k_buf,"Can't open DOS cache: %s",dtmp->name);
  407.             fatal(tmp_20k_buf);
  408.         }
  409.  
  410.         for(j = 0; j < stream->cachesize; j += CB_SIZE){
  411.             dtmp->cbase = j;
  412.             dcwriteb(dtmp);
  413.         }
  414.         dtmp->cbase = 0;
  415.         }
  416.         else{
  417.         /* init new entries */
  418.         fseek(dtmp->dcf, j * sizeof(METACACHE), SEEK_SET);
  419.         memset((void *)&ctmp, 0, sizeof(METACACHE));
  420.         for(;j < stream->cachesize; j++){
  421.             n = fwrite((void *)&ctmp,sizeof(METACACHE),1,dtmp->dcf);
  422.             if(n != 1L)
  423.               fatal("Cache init failed on fwrite");
  424.         }
  425.         }
  426.         }
  427.         break;
  428.  
  429.       case CH_ELT:            /* return elt */
  430.       case CH_MAKEELT:            /* short elt, make if necessary */
  431.       case CH_LELT:            /* return long elt */
  432.       case CH_MAKELELT:            /* long elt, make if necessary */
  433.     ret = (stream->scache) ? (void *) &dcget(stream, msgno)->cachel.mc
  434.                            : (void *) &dcget(stream, msgno)->cachel.lc;
  435.     break;
  436.  
  437.       case CH_FREE:            /* free (l)elt */
  438.     /* 
  439.      * SEE WARNING ABOVE! if we ever need lock counts
  440.      * this should call an appropriate mail_free_XXX-like 
  441.      * function.
  442.      */
  443.     dcget(stream, msgno)->use = 0;
  444.     break;
  445.  
  446.       case CH_EXPUNGE:            /* expunge cache slot */
  447.     {                /* slide down remainder of cache */
  448.         METACACHE *dc_copy=(METACACHE *)fs_get(sizeof(METACACHE));
  449.  
  450. /*
  451.  * OPTIMIZE: this could be made a little more efficient by using offset
  452.  *           into the current block in memory, and copying blocks of 
  453.  *           elt's at a time rather than individually.
  454.  */
  455.         for (i = msgno+1; i <= stream->nmsgs; ++i){
  456.         memcpy((void *)dc_copy,
  457.                (void *)dcget(stream, i),
  458.                sizeof(METACACHE));
  459.         if(stream->scache) 
  460.           dc_copy->cachel.mc.msgno = i - 1L;
  461.         else
  462.           dc_copy->cachel.lc.elt.msgno = i - 1L;
  463.  
  464.         memcpy((void *)dcget(stream, i-1),
  465.                (void *)dc_copy,
  466.                sizeof(METACACHE));
  467.         }
  468.  
  469.         fs_give((void **)&dc_copy);
  470.         memset((void *)dcget(stream, stream->nmsgs),
  471.            0, 
  472.            sizeof(METACACHE));
  473.     }
  474.  
  475.     break;
  476.  
  477.     default:
  478.       fatal ("Bad dos_cache op");
  479.       break;
  480.     }
  481.  
  482.     return ret;
  483. }
  484.  
  485.  
  486.  
  487. /*
  488.  * ***** FOR DEBUGGING *****
  489.  */
  490. void dumpmetacache(stream)
  491. MAILSTREAM *stream;
  492. {
  493.     FILE *fp;
  494.     long i;
  495.     size_t  n;
  496.     METACACHE ce;
  497.     DOSCACHE *dp = (DOSCACHE *)stream->cache.c;
  498.  
  499.     if((fp=fopen("\\tmp\\cache.out","a")) == NULL)
  500.     return;
  501.     if(!stream->cache.c){
  502.     fprintf(fp,"NO CACHE ASSOCIATED WITH STREAM!!!\n");
  503.     }
  504.     else{
  505.         fprintf(fp,"****** cache has %ld entries (%d element blocks)\n", 
  506.         stream->cachesize, CB_SIZE);
  507.     fprintf(fp,"Those in core are:\n");
  508.     for(i=0; i < CB_SIZE; i++){
  509.       fprintf(fp,"  %d) ", i+1);
  510.       if(!dp->mcb[i].use){
  511.          fprintf(fp,"EMPTY\n");
  512.       }
  513.       else{
  514.          fprintf(fp,"# %ld, lock = %d, size = %ld\n", 
  515.             dp->mcb[i].cachel.mc.msgno,
  516.             dp->mcb[i].cachel.mc.lockcount,
  517.             dp->mcb[i].cachel.mc.rfc822_size);
  518.       }
  519.     }
  520.  
  521.     fprintf(fp,"Those on disk are:\n");
  522.     fseek(dp->dcf, 0L, SEEK_SET);
  523.     for(i=0; i < stream->cachesize; i++){
  524.       fprintf(fp,"  %d) ", i+1);
  525.       n = fread(&ce, sizeof(METACACHE), 1, dp->dcf);
  526.       if(n != 1){
  527.          fprintf(fp,"PROBLEM READING ENTRY!!!\n");
  528.          break;
  529.       }
  530.       if(!ce.use){
  531.          fprintf(fp,"EMPTY\n");
  532.       }
  533.       else{
  534.          fprintf(fp,"# %ld, lock = %d, size = %ld\n", 
  535.             ce.cachel.mc.msgno,
  536.             ce.cachel.mc.lockcount,
  537.             ce.cachel.mc.rfc822_size);
  538.       }
  539.     }
  540.     }
  541.     fclose(fp);
  542. }
  543.  
  544.  
  545. #ifndef    _WINDOWS
  546. /*
  547.  *
  548.  */
  549. unsigned
  550. alarm(t)
  551.     unsigned t;
  552. {
  553. }
  554. #endif
  555. #endif
  556.